package com.qn.config.websocket;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * websocket核心类
 *
 * @author olo
 */
@ServerEndpoint("/webSocketIMServer")
@Component
@Slf4j
public class WebSocketServer {
    /**
     * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static final AtomicInteger ONLINE_NUM = new AtomicInteger();
    /**
     * concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketServer对象。
     */
    private static final ConcurrentHashMap<String, Session> SESSION_POOLS = new ConcurrentHashMap<>();

    /**
     * 向客户端发送消息
     *
     * @param session 参数说明
     * @param message 参数说明
     * @description TODO
     * @author olo
     * @date 2021/10/20
     */
    public void sendMessage(Session session, String message) throws IOException {
        synchronized (session) {
            session.getAsyncRemote().sendText(message);
        }
    }

    /**
     * 发送给指定的用户
     *
     * @param uid    参数说明
     * @param object 参数说明
     * @description TODO
     * @author olo
     * @date 2021/10/20
     */
    public void sendThisUser(String uid, Object object) {
        Session session = SESSION_POOLS.get(uid);
        if (session.isOpen()) {
            try {
                sendMessage(session, JSON.toJSONString(object));
            } catch (IOException e) {
                log.error(("向" + uid + "响应数据时出现异常:" + e));
            }
        }
    }

    /**
     * 建立连接成功调用
     *
     * @description TODO
     * @author olo
     * @date 2021/10/20
     */
    @OnOpen
    public void onOpen() {
        addOnlineCount();
        //连接成功就直接向前端发送队列状态
        log.info("websocket连接成功" + SESSION_POOLS);
    }

    /**
     * 关闭连接时调用
     *
     * @description TODO
     * @author olo
     * @date 2021/10/20
     */
    @OnClose
    public void onClose() {
        subOnlineCount();
        log.info("断开webSocket连接！当前连接数为" + ONLINE_NUM);
    }

    /**
     * 收到客户端信息
     *
     * @param session 用户会话
     * @param message 接收的消息
     * @description TODO
     * @author olo
     * @date 2021/10/20
     */
    @OnMessage
    public void onMessage(Session session, String message) {
        //将该用户的session放入map以便数据的发送
        SESSION_POOLS.put(message, session);
    }

    /**
     * 错误时调用
     *
     * @param throwable 异常
     * @description TODO
     * @author olo
     * @date 2021/10/20
     */
    @OnError
    public void onError(Throwable throwable) {
        log.error("发生错误" + throwable.getCause());
    }

    public static void addOnlineCount() {
        ONLINE_NUM.incrementAndGet();
    }

    public static void subOnlineCount() {
        ONLINE_NUM.decrementAndGet();
    }
}
